# -*- coding: utf-8 -*-
# https://blog.csdn.net/weixin_52040868
# 公众号：测个der
# 微信：qing_an_an


import sys
import serial
import threading
import msvcrt
from PySide6.QtCore import Qt, QThread, Signal
from PySide6.QtGui import QTextCursor
from PySide6.QtWidgets import QApplication, QMainWindow, QPlainTextEdit, QVBoxLayout, QWidget

class SerialTerminal(object):
    def __init__(self, COM, PORT):
        self.COM = COM
        self.PORT = PORT
        self.buffer = ""

    def Getch(self):
        """获取键盘字节"""
        return msvcrt.getch().decode()

    def Start(self, received_data_signal):
        """运行"""
        self.received_data = received_data_signal  # 保存received_data信号的引用
        self.ser = serial.Serial(self.COM, self.PORT)  # 设置串口名称和波特率
        self.ser.write(f"\n".encode())

        self.Read_thread = threading.Thread(target=self.Read_serial)
        self.Read_thread.daemon = True
        self.Read_thread.start()

    def Read_serial(self):
        while True:
            try:
                count = self.ser.inWaiting()
                if count != 0:
                    # 读取内容并回显
                    recv = self.ser.read(count)
                    self.buffer += recv.decode()
                    self.received_data.emit(self.buffer)  # 发出received_data信号

            except UnicodeDecodeError as e:
                pass

    def Clear_buffer(self):
        self.buffer = ""

class SerialThread(QThread):
    received_data = Signal(str)

    def __init__(self, COM, PORT):
        super().__init__()
        self.COM = COM
        self.PORT = PORT

    def run(self):
        self.serial_terminal = SerialTerminal(self.COM, self.PORT)
        self.serial_terminal.Start(self.received_data)  # 传递received_data信号给SerialTerminal类

class MainWindow(QMainWindow):
    def __init__(self, COM, PORT):
        super().__init__()
        self.COM = COM
        self.PORT = PORT

        self.serial_thread = None

        self.initUI()

    def initUI(self):
        self.setWindowTitle("Serial Terminal")

        self.text_edit = QPlainTextEdit()
        self.text_edit.setReadOnly(True)
        self.text_edit.setLineWrapMode(QPlainTextEdit.NoWrap)  # 禁用自动换行

        layout = QVBoxLayout()
        layout.addWidget(self.text_edit)

        central_widget = QWidget()
        central_widget.setLayout(layout)
        self.setCentralWidget(central_widget)

    def start_serial_thread(self):
        self.serial_thread = SerialThread(self.COM, self.PORT)
        self.serial_thread.received_data.connect(self.on_received_data)
        self.serial_thread.start()

    def on_received_data(self, data):
        self.text_edit.setPlainText(data)
        self.text_edit.moveCursor(QTextCursor.End)
        self.text_edit.ensureCursorVisible()
        scrollbar = self.text_edit.verticalScrollBar()
        scrollbar.setValue(scrollbar.maximum())

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            self.close()
        elif event.key() == Qt.Key_Backspace:
            if self.serial_thread is not None:
                serial_terminal = self.serial_thread.serial_terminal
                if len(serial_terminal.buffer) > 0:
                    # 从串口缓存中删除最后一个字节
                    serial_terminal.buffer = serial_terminal.buffer[:-1]
                    # 删除文本框中的最后一个字符
                    cursor = self.text_edit.textCursor()
                    cursor.deletePreviousChar()
        else:
            if self.serial_thread is not None:
                ch = event.text()
                self.serial_thread.serial_terminal.ser.write(ch.encode())

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = MainWindow('COM3', 115200)
    window.start_serial_thread()
    window.show()

    sys.exit(app.exec())
